package com.qf.filter;

import com.alibaba.fastjson.JSON;
import com.qf.entity.R;
import com.qf.util.TokenTong;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;



/**
 * 局部过滤器
 */
@Component
public class TokenLimitFilter implements GatewayFilter, Ordered {

    //path - new TokenTong()
    private Map<String, TokenTong> tokenMap = new HashMap<>();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //url过滤器 - 同一个接口被一个令牌桶限制 /a/b xxxx
        //获得用户请求
        ServerHttpRequest request = exchange.getRequest();
        //获得用户的请求的url
        String path = request.getPath().toString();
//        System.out.println("用户访问了：" + path);

//        TokenTong tokenTong = null;
//        //根据path创建令牌桶 - 不同的path应该使用不同的令牌桶
//        if (!tokenMap.containsKey(path)) {
//            //初始化令牌桶
//            tokenTong = new TokenTong(path, 100, 100);
//            //放入Map
//            tokenMap.put(path, tokenTong);
//        } else {
//            //已经初始化过了
//            tokenTong = tokenMap.get(path);
//        }

        //获得相应Path对应的令牌桶对象
        TokenTong tokenTong = tokenMap.computeIfAbsent(path, s -> {
            return new TokenTong(s, 5, 1);
        });

        //尝试获取令牌
        if (tokenTong.getTokensNow(1)) {
            System.out.println("获得令牌，请求放行：" + new Date());
            //放行
            return chain.filter(exchange);
        }

        //未获得令牌，则返回繁忙信息
        ServerHttpResponse response = exchange.getResponse();

        //准备一个返回对象
        R returnR = new R().setCode(R.Code.ERROR).setMsg("服务器繁忙，请稍后再试！");
        DataBuffer dataBuffer = null;
        Mono<Void> voidMono = null;
        try {
            response.getHeaders().put("Content-Type", Collections.singletonList("application/json;charset=utf-8"));
            dataBuffer = response.bufferFactory().wrap(JSON.toJSONString(returnR).getBytes("utf-8"));
            voidMono = response.writeWith(Mono.just(dataBuffer));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return voidMono;
    }

    @Override
    public int getOrder() {
        return 200;
    }
}
